﻿
var ButtonObject = function(Settings) {
	this.dom = document.createElement('div');
	this.onClickCall = null; //the call that will be called when the button is clicked
	
	var This = this,
		DefaultSettings = {
			title : '' //String, the title of the button
			,iconURL : '' //String, the icon's URL
			,maxWidth : 0 //Integer, the maximum width of the icon, if left at 0 the actual width of the icon is used
			,maxHeight : 0 //Integer, the minimum width of the icon, if left at 0 the actual height of the icon is used
			,minScale : 0.75 //Number, the minimum scale of the icon i.e. the resting position of the button, when you hover over the button then it will go to the max width
			,time : 200	//Integer, the time it takes the object to move from resting scale to the maximum scale i.e.  1.0
		},
		
		link = document.createElement('a'),
		icon = new Image(),
		
		status = 0,
			//0 - resting
			//1 - getting bigger (activating)
			//2 - getting smaller (disabling)
			//3 - image loading has an error
			//4 - icon loading was aborted
			//5 - hasBeenStopped
			//6 - toggledUp
			
		scale = 0,
		
		scaleJump = null, //system variable, shows how much the scale changes per frame
		framePauseTime = null, //system variable, shows how many milliseconds the movement frame will wait
		isTouch = false //shows if the device is a touch device or not
	;
	
	/********************************************************************************
	These variables are commented out, because they need to be added using prototype.
	---------------------------------------------------------------------------------
	
	this.Settings = {}; //A second Settings object that will be applied to all of the [ButtonObjects]s
		
	********************************************************************************/
	
	function _init() {
		
		//Merges all of the settings into the "Settings" object
		Settings = $.extend({}
			,DefaultSettings
			,typeof This.Settings != 'object' ? {} : This.Settings
			,typeof Settings != 'object' ? {} : Settings
		);
				
		icon.onerror = function() {
			imageFailed(3);
		};
		icon.onabort = function() {			
			imageFailed(4);
		};
		icon.onload = function() { 
		
			if(!Settings.maxWidth) {
				Settings.maxWidth = this.width;
			}
			if(!Settings.maxHeight) {
				Settings.maxHeight = this.height;
			}
			
			imageLoaded(); 
		};		
		
		This.dom.style.marginLeft = '5px';
		setFrameRate(24);
	}
	
	function isActive() {
		switch(status) {
			case 6:
			case 5:
				return false;
			default:
				return true;
		}
	}
	function mouseOver() {
		
		if(status == 1)
			return;
			
		if(isActive())	{
			status = 1;			
		}
		
		if(!isTouch) {
			$(icon).unbind('mouseover', mouseOver);
			$(icon).unbind('mousemove', mouseOver);
			$(document).bind('mousemove', mouseOut);
		}
		
		if(Settings.title.length) {
			Hint.show(Settings.title);
		}
	}
	function mouseOut() {
		if(status == 2)
			return;
		
		if(isActive())	{
			status = 2;			
		}	

		if(!isTouch) {
			Hint.hide();
			$(icon).bind('mouseover', mouseOver);
			$(icon).bind('mousemove', mouseOver);
			$(document).unbind('mousemove', mouseOut);
		}
	}
	function setFrameRate(frameRate) {
		framePauseTime = Math.ceil(1000 / frameRate);
		scaleJump = Math.abs((1 - Settings.minScale) / (Settings.time / framePauseTime));
	}
	function imageFailed(newStatus) {
		status = newStatus;
		var a = document.createElement('a');
			
		link.href = location.href;
		link.appendChild(document.createTextNode(Settings.title));
		link.style.whileSpace = 'nowrap';
		
		This.dom.appendChild(link);
	}
	function imageLoaded() {
		
		var a = document.createElement('a');
		
		Utility.MakeInlineBlockDOM(This.dom);
		
		This.dom.style.width = Settings.maxWidth + 'px';
		This.dom.style.height = Settings.maxHeight + 'px';
		This.dom.style.overflow = 'hidden';
		This.dom.style.direction = 'ltr';
							
		link.href = link.href = location.href;
				
		link.style.display = 'block';
		link.style.width = Settings.maxWidth + 'px';
		link.style.height = Settings.maxHeight + 'px';
		
		icon.style.borderWidth = '0px';		
		setScale(Settings.minScale);
		
		link.style.textAlign = 'left';
		
		link.appendChild(icon);
		This.dom.appendChild(link);
		
		setInterval(function(){ frameCall(); }, framePauseTime);
	}
	function onClick() {
	
		window.focus();
		
		if(isActive() && typeof This.onClickCall == 'function'){
			This.onClickCall();
		}
	}
	function setScale(newScale) {
		scale = newScale;
		
		var width = Math.floor(Settings.maxWidth * newScale), 
			height = Math.floor(Settings.maxHeight * newScale),
			temp;
					
		icon.style.width = width + 'px';
		icon.style.height = height + 'px';
		
		temp = Math.round((Settings.maxWidth - width) / 2);
		icon.style.marginLeft = temp + 'px';
		icon.style.marginRight = temp + 'px';
		
		temp = Math.round((Settings.maxHeight - height) / 2);
		icon.style.marginTop = temp + 'px';
		icon.style.marginBottom = temp + 'px';
							
		if(document.all) {
			icon.style.filter = 'Alpha(Opacity=' + Math.floor(newScale * 100) + ')';
		} else {
			icon.style.opacity = newScale;
		}
	}
	function frameCall() {
		
		var temp;
		
		switch(status) {
			case 1:
			case 6:
				temp = scale + scaleJump;
				
				if(temp > 1)
					temp = 1;
					
				if(temp == 1) {
					if(status == 6)
						status = 5;
					else
						status = 0;
				}				
			break;
			case 2: 
				temp = scale - scaleJump;
				if(temp < Settings.minScale)
					temp = Settings.minScale;
				if(temp == Settings.minScale)
					status = 0;
			break;
			default: 
				return;
		}
		
		setScale(temp);
	}
	
	
	this.load = function(src) {
	/*
		Loads the Icon into the DOM, must be called when [ButtonObject].dom is visible in DOM Tree.
		src - [Optional] String, allows the client programmer to redefine the button icon to a different picture than in the "Settings" object
	*/
		
		if(typeof document.body.ontouchstart == 'object') {
			isTouch = true; 
			$(icon).bind('touchend', function(e) {
				
				e.stopPropagation();
				
				onClick();
				mouseOut();
				
				return false;
			});
			icon.ontouchstart = function() {
				mouseOver();
				return false;
			};
			$(document).bind('touchend', function() {	
			
				mouseOut();
				Hint.hide();
			});
			
			link.onclick = function() { return false; };
		} else {
			link.onclick = function() { return false; };
			icon.onclick = function() { onClick(); }; //the separation between the link and the icon is done so that if the onclick event is faulty then then the error will be thrown
			
			var eventCall = function(e) {
				e.stopPropagation();
				mouseOver();
			};
			
			$(icon).bind('mouseover', eventCall);
			$(icon).bind('mousemove', eventCall);
		}
		
		icon.src = typeof src == 'string' ? src : Settings.iconURL;
		Hint.load();		
	};
	this.activate = function() {
		status = 2;
		link.style.cursor = 'pointer';
	};
	this.toggleUp = function() {
	/*
		The button will be called into the Active position and the on click event wont fire anymore
	*/
		status = 6;
		link.style.cursor = 'default';
	};
	
	_init();
};